/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_lwphp.h"

#define LWPHP_STARTUP(module) ZEND_MODULE_STARTUP_N(lw_##module)(INIT_FUNC_ARGS_PASSTHRU)
/* If you declare any globals in php_myfunctions.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(myfunctions)
*/

/* True global resources - no need for thread safety here */
static int le_lwphp;
static zval *config;
static int execute_times=0;

/* {{{ myfunctions_functions[]
 *
 * Every user visible function must have an entry in myfunctions_functions[].
 */
const zend_function_entry lwphp_functions[] = {
	PHP_FE(C,	NULL)
	PHP_FE(test,	NULL)
#if ((PHP_MAJOR_VERSION == 5) && (PHP_RELEASE_VERSION <= 3))
        {NULL, NULL, NULL}
#else
	PHP_FE_END	/* Must be the last line in myfunctions_functions[] */
#endif
};
/* }}} */

/* {{{ myfunctions_module_entry
 */
zend_module_entry lwphp_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"lwphp",
	lwphp_functions,
	PHP_MINIT(lwphp),
	PHP_MSHUTDOWN(lwphp),
	PHP_RINIT(lwphp),		/* Replace with NULL if there's nothing to do at request start */
	PHP_RSHUTDOWN(lwphp),	/* Replace with NULL if there's nothing to do at request end */
	PHP_MINFO(lwphp),
#if ZEND_MODULE_API_NO >= 20010901
	PHP_LWPHP_VERSION,
#endif
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_LWPHP
ZEND_GET_MODULE(lwphp)
#endif

/* {{{ PHP_INI
 */
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY("myfunctions.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_myfunctions_globals, myfunctions_globals)
    STD_PHP_INI_ENTRY("myfunctions.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_myfunctions_globals, myfunctions_globals)
PHP_INI_END()
*/
/* }}} */

/* }}} */

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(lwphp)
{
//	array_init(config);
	/* If you have INI entries, uncomment these lines 
	REGISTER_INI_ENTRIES();
	*/
	LWPHP_STARTUP(smarty);
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(lwphp)
{
	/* uncomment this line if you have INI entries
	UNREGISTER_INI_ENTRIES();
	*/
	//zend_hash_destory(config->ht);
	//zend_hash_destroy(config->value.ht);
    //pefree(config, 1);
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(lwphp)
{
	MAKE_STD_ZVAL(config);
	//array_init(return_value);
	array_init(config);
	//ALLOC_INIT_ZVAL(config); 
	//Z_TYPE_P(config) = IS_ARRAY;
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(lwphp)
{
	//zend_hash_destroy(config->value.ht);
	//efree(config->value.ht);
	//pefree(config->value.ht, 1);
	
	//pefree(config, 1);
	zval_ptr_dtor(&config);
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(lwphp)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "LWPHP support", "enabled");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini
	DISPLAY_INI_ENTRIES();
	*/
}
/* }}} */



/* {{{ proto string self_concat(string str, int n)
    */
zval* getConfig(zval *find,char *key){
	zval **result;
	if(strstr(key,".")){
		char *subkey;
		key = strtok(key, ".");
		subkey = strtok(NULL, ".");
		if (zend_hash_find(Z_ARRVAL_P(find), key, strlen(key) + 1, (void **) &result) == FAILURE){
			zval *false;
			ZVAL_NULL(false);
			return false;
		}else{
			return getConfig(*result, subkey);
		}
	}else{
		if (zend_hash_find(Z_ARRVAL_P(find), key, strlen(key) + 1, (void **) &result) == FAILURE){//直接获取
			zval *false;
			MAKE_STD_ZVAL(false);
			ZVAL_NULL(false);
			return false;
		}else{
			return *result;
		}
	}
}


void setConfig(char *key, uint len,zval *value){
	if(Z_TYPE_P(value) == IS_STRING){
		add_assoc_string(config, key, Z_STRVAL_P(value), 1);
		return;
	}else if(Z_TYPE_P(value) == IS_ARRAY){
		Z_ADDREF_P(value);
		add_assoc_zval(config, key, value);
		return;
	}else if (Z_TYPE_P(value) == IS_BOOL){
		add_assoc_bool(config, key, Z_BVAL_P(value));
		return;
	}
}
PHP_FUNCTION(test){
	zval *val, **newVal;
	//Bucket *pos;
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &val) == FAILURE) {
		return;
	}
	//zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(val), &pos);
	//zend_hash_move_forward_ex(Z_ARRVAL_P(val), &pos);
	//zend_hash_get_current_data_ex( (*val).value.ht, (void **) &newVal, &pos);
	//*newVal = pos->pData;
	//php_printf("%);
	//php_var_dump((zval *)*newVal,1 TSRMLS_CC);
}
PHP_FUNCTION(C)
{
	uint argc = ZEND_NUM_ARGS();
	if(argc == 0){
		RETURN_ZVAL(config, 1, 0);
	}else if(argc == 1){
		zval *value;
		if (zend_parse_parameters(argc TSRMLS_CC, "z", &value) == FAILURE) {
			return;
		}
		if (Z_TYPE_P(value) == IS_ARRAY) {//配置合并
			//php_var_dump(&value, 1 TSRMLS_CC);;
			zend_hash_merge(Z_ARRVAL_P(config), Z_ARRVAL_P(value), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1);
			RETURN_ZVAL(config, 1, 0);
			return;
		} else if(Z_TYPE_P(value) == IS_STRING) {//获取配置
			zval *s = getConfig(config, value->value.str.val);
			RETURN_ZVAL(s, 1, 0);
			return;
		}
	} else if (argc == 2) {
		char *key;
		uint len;
		zval *value;//用来保存传入的第二个参数
		if (zend_parse_parameters(argc TSRMLS_CC, "sz", &key, &len, &value) == FAILURE) {
			return;
		}
		setConfig(key, len, value);
		RETURN_ZVAL(config, 1, 0);
	}
		
}
/* }}} */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
